/**
 * LangChain WebSocket 专用连接器
 * 用于与LangChain后端建立WebSocket连接
 */
import SockJS from 'sockjs-client';

class LangChainWebSocket {
  constructor() {
    this.socket = null;
    this.connected = false;
    this.messageHandlers = new Map();
    this.reconnectAttempts = 0;
    this.reconnectTimeout = 3000;
    this.maxReconnectAttempts = 5;
  }

  /**
   * 连接到LangChain WebSocket服务器
   * @param {string} serverUrl - WebSocket服务器URL
   * @returns {Promise<boolean>} - 是否成功连接
   */
  connect(serverUrl = 'http://localhost:8080/iff/langchain-ws') {
    return new Promise((resolve, reject) => {
      if (this.connected && this.socket) {
        resolve(true);
        return;
      }

      try {
        console.log(`尝试连接到LangChain WebSocket: ${serverUrl}`);
        this.socket = new SockJS(serverUrl);

        this.socket.onopen = () => {
          console.log('LangChain WebSocket连接成功');
          this.connected = true;
          this.reconnectAttempts = 0;
          resolve(true);
        };

        this.socket.onmessage = (event) => {
          try {
            const message = JSON.parse(event.data);
            this.handleMessage(message);
          } catch (error) {
            console.error('解析WebSocket消息时出错:', error);
          }
        };

        this.socket.onclose = () => {
          console.log('LangChain WebSocket连接关闭');
          this.connected = false;
          this.handleReconnect(serverUrl).catch(() => {
            reject(new Error('WebSocket连接关闭且无法重连'));
          });
        };

        this.socket.onerror = (error) => {
          console.error('LangChain WebSocket错误:', error);
          this.connected = false;
          reject(error);
        };
      } catch (error) {
        console.error('创建LangChain WebSocket连接时出错:', error);
        reject(error);
      }
    });
  }

  /**
   * 处理连接断开后的重连逻辑
   * @param {string} serverUrl - 服务器URL
   * @returns {Promise<boolean>} - 是否重连成功
   * @private
   */
  async handleReconnect(serverUrl) {
    if (this.reconnectAttempts >= this.maxReconnectAttempts) {
      console.error('达到最大重连尝试次数');
      return false;
    }

    this.reconnectAttempts++;
    console.log(`尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);

    return new Promise((resolve) => {
      setTimeout(async () => {
        try {
          const success = await this.connect(serverUrl);
          resolve(success);
        } catch (error) {
          resolve(false);
        }
      }, this.reconnectTimeout);
    });
  }

  /**
   * 关闭WebSocket连接
   */
  disconnect() {
    if (this.socket) {
      this.socket.close();
      this.socket = null;
      this.connected = false;
    }
  }

  /**
   * 发送查询到LangChain服务器
   * @param {string} query - 查询文本
   * @returns {Promise<Object>} - 查询响应
   */
  sendQuery(query) {
    return new Promise((resolve, reject) => {
      if (!this.connected) {
        reject(new Error('WebSocket未连接'));
        return;
      }

      // 创建唯一ID用于标识此次查询
      const queryId = Date.now().toString();
      
      // 设置响应处理器
      const responseHandler = (message) => {
        if (message.type === 'query_response' && message.queryId === queryId) {
          // 找到匹配的响应
          this.removeMessageHandler('query_response', responseHandler);
          resolve(message);
        }
      };

      // 添加响应处理器
      this.addMessageHandler('query_response', responseHandler);

      // 设置超时
      const timeout = setTimeout(() => {
        this.removeMessageHandler('query_response', responseHandler);
        reject(new Error('查询超时'));
      }, 30000); // 30秒超时

      try {
        // 发送查询
        this.socket.send(JSON.stringify({
          type: 'query',
          content: query,
          queryId: queryId,
          timestamp: Date.now()
        }));
      } catch (error) {
        clearTimeout(timeout);
        this.removeMessageHandler('query_response', responseHandler);
        reject(error);
      }
    });
  }

  /**
   * 处理接收到的WebSocket消息
   * @param {Object} message - 消息对象
   * @private
   */
  handleMessage(message) {
    if (!message || !message.type) {
      console.warn('收到无效WebSocket消息:', message);
      return;
    }

    // 调用该类型的所有消息处理器
    const handlers = this.messageHandlers.get(message.type) || [];
    handlers.forEach(handler => {
      try {
        handler(message);
      } catch (error) {
        console.error(`执行消息处理器时出错 (type=${message.type}):`, error);
      }
    });

    // 触发通用事件，使外部代码可以监听
    const event = new CustomEvent('langchain:message', { 
      detail: message 
    });
    window.dispatchEvent(event);
  }

  /**
   * 添加消息处理器
   * @param {string} type - 消息类型
   * @param {Function} handler - 处理函数
   */
  addMessageHandler(type, handler) {
    if (!this.messageHandlers.has(type)) {
      this.messageHandlers.set(type, []);
    }
    
    this.messageHandlers.get(type).push(handler);
  }

  /**
   * 移除消息处理器
   * @param {string} type - 消息类型
   * @param {Function} handler - 处理函数
   */
  removeMessageHandler(type, handler) {
    if (!this.messageHandlers.has(type)) {
      return;
    }
    
    const handlers = this.messageHandlers.get(type);
    const index = handlers.indexOf(handler);
    
    if (index !== -1) {
      handlers.splice(index, 1);
    }
  }

  /**
   * 是否已连接
   * @returns {boolean} - 连接状态
   */
  isConnected() {
    return this.connected;
  }
}

// 创建并导出单例
const langchainWebSocket = new LangChainWebSocket();
export default langchainWebSocket; 